#ifndef BOOK_H_INCLUDED
#define BOOK_H_INCLUDED

#include <fitz.h>
#include <mupdf.h>

#include "Typedef.h"
#include "Digest.h"
#include "Log.h"
#include "Note.h"
#include "Review.h"
#include "Tag.h"

class Note;
class Review;
class Tag;
class History;

enum _BookStatus
{
    BookUnread,
    BookInterested,
    BookReading,
    BookRead
};

class GenreData
{
public:
    uint32_t GenreID;
    string name;
};

class DigestData
{
public:
    string digest_hex;
};

class BookInfo
{
public:
    uint32_t PageCount;
    uint32_t BookID;

    string BookFilePath;
    string BookName;
    string Author;
    string ISBN;
    enum _BookStatus BookStatus;

    GenreData BookGenre;
    DigestData BookDigest;

public:
    static enum _BookStatus CharsToStatus(Bupchar status);
    static string StatusToString(enum _BookStatus status);

    static string BookFilePathToName(string path);
};

class BPObject
{
public:
    BPObject(){};
    virtual ~BPObject(){};
};

class Book : public BPObject
{
public:
    Book(Bpchar FilePath);
    ~Book();

    /*temporarily expose Info to outside, during test period only.*/
    BookInfo Info;
private:
    list<Note*> Notes;
    list<Review*> Reviews;
    /*Notes and Reviews belongs to on Book only,
    one tag can be attached to many books.*/
    list<Tag*> Tags;
    list<History*> Historys;

private:
    Book();

private:
    Bbool IsNotesGot;
    Bbool IsReviewsGot;
    Bbool IsTagsGot;
    Bbool IsHistorysGot;

    Bbool IsBook;

public:
    list<History*>* GetHistorysPtr();

public:
    Bbool Verify();
    Bbool GetIsBook();

    Bbool GetIsNotesGot();
    Bbool GetIsReviewsGot();
    Bbool GetIsTagsGot();
    Bbool GetIsHistorysGot();

    void SetIsNotesGot(Bbool Status);
    void SetIsReviewsGot(Bbool Status);
    void SetIsTagsGot(Bbool Status);
    void SetIsHistorysGot(Bbool Status);

    void ClearHistorys();
    void ClearReviews();
    void ClearTags();
    void ClearNotes();

    BPcode AddHistory(History* history);
    History* GetHistoryByID(uint32_t HID);
    BPcode DeleteHistoryByID(uint32_t HistoryID);

    BPcode AddNote(Note* note);
    Note* GetNoteByID(uint32_t NoteID);
    BPcode DeleteNoteByID(uint32_t NoteID);

    BPcode AddReview(Review* review);
    Review* GetReviewByID(uint32_t ReviewID);
    BPcode DeleteReviewByID(uint32_t ReviewID);

    BPcode AddTagByName(string TagName);
    BPcode DeleteTagByID(uint32_t TagID);
    BPcode DeleteTagByName(string TagName);

private:
    list<History*>::iterator* GetHistoryIteratorByID(uint32_t HID);
};

#endif // BOOK_H_INCLUDED
